package com.dianping.puma.storage.index;
import com.dianping.puma.common.AbstractLifeCycle;
import com.dianping.puma.storage.bucket.BucketFactory;
import com.dianping.puma.storage.bucket.ReadBucket;
import org.apache.commons.lang3.tuple.Pair;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
public abstract class SingleReadIndexManager<K, V> extends AbstractLifeCycle
implements ReadIndexManager<K, V> {
private final File file;
private final int bufSizeByte;
private final int avgSizeByte;
protected ReadBucket readBucket;
public SingleReadIndexManager(File file, int bufSizeByte, int avgSizeByte) {
this.file = file;
this.bufSizeByte = bufSizeByte;
this.avgSizeByte = avgSizeByte;
}
@Override
protected void doStart() {
readBucket = BucketFactory.newLineReadBucket(file, bufSizeByte, avgSizeByte);
readBucket.start();
}
@Override
protected void doStop() {
if (readBucket != null) {
readBucket.stop();
}
}
@Override
public V findOldest() throws IOException {
checkStop();
try {
byte[] data = readBucket.next();
return decode(data).getRight();
} catch (EOFException eof) {
return null;
}
}
@Override
public V findLatest() throws IOException {
checkStop();
byte[] data = null;
try {
while (!isStopped()) {
data = readBucket.next();
}
return null;
} catch (EOFException eof) {
if (data == null) {
return null;
}
return decode(data).getRight();
}
}
@Override
public V find(K indexKey) throws IOException {
checkStop();
byte[] data;
Pair<K, V> oldPair = null;
try {
while (true) {
data = readBucket.next();
if (data != null) {
Pair<K, V> pair = decode(data);
if (!greater(indexKey, pair.getLeft())) {
if (oldPair == null) {
throw new IOException("failed to find.");
} else {
return oldPair.getRight();
}
} else {
oldPair = pair;
}
}
}
} catch (EOFException eof) {
if (oldPair == null) {
throw new IOException("failed to find.");
} else {
return oldPair.getRight();
}
}
}
protected abstract boolean greater(K aIndexKey, K bIndexKey);
protected abstract Pair<K, V> decode(byte[] data) throws IOException;
}